<%
  Private Const INIT_SIZE = 1024
  Private Const INIT_GAP_SIZE = 128
  Class ArrayElement
    Public IsTaken
    Public Value
    Public Key
  End Class
  
  Class HashTable
    '私有变量
    Private mCount
    Private mCurrentSize
    Private mArray
    Private mSize
    Private mGapSize
    
    '类的初始化和清空
    
    Private Sub Class_Initialize()
      resizeArray INIT_SIZE
      Me.GapSize = INIT_GAP_SIZE
    End Sub
    
    Private Sub Class_Terminate()

    End Sub
    
    '私有方法
    
    Private Sub resizeArray(ByVal newSize)
      If mCount > 0 Then
        ReDim Preserve mArray(newSize)
      Else
        ReDim mArray(newSize)
      End If
      mCurrentSize = newSize
    End Sub
    
    Private Sub expandArray()
      mCurrentSize = mCurrentSize + mGapSize
      resizeArray mCurrentSize
    End Sub

    Private Function findIndex(ByVal keyword)
      Dim index, startIndex
      
      index = calcInitIndex(keyword)
      startIndex = index
      
      Do While True
        If VarType(mArray(index)) > 0 Then
          If mArray(index).IsTaken = True And mArray(index).Key = keyword Then
            findIndex = index
            Exit Function
          Else
            index = (index + 1) Mod mCurrentSize
            If index = 0 Then index = index + 1
            If startIndex = index Then
              findIndex = -1
              Exit Function
            End If
          End If
        Else
          index = (index + 1) Mod mCurrentSize
          If index = 0 Then index = index + 1
          If startIndex = index Then
            findIndex = -1
            Exit Function
          End If
        End If
      Loop
    End Function

    Private Function findFreeIndex(ByVal keyword)
      Dim index, startIndex
      index = calcInitIndex(keyword)
      
      startIndex = index
      Do While True
        If VarType(mArray(index)) > 0 Then
          If mArray(index).Key = keyword Then
            findFreeIndex = index
            Exit Function
          Else
            index = (index + 1) Mod mCurrentSize
            If index = 0 Then index = index + 1
            If startIndex = index Then
              findFreeIndex = -1
              Exit Function
            End If
          End If
        Else
          findFreeIndex = index
          Exit Function
        End If
      Loop
    End Function

    Private Function calcInitIndex(ByVal keyword)
      Dim index, i
      Dim bytes
      bytes = stringToByteArray(keyword)
      For i = 1 To UBound(bytes)
        index = index + bytes(i)
        If index > mCount Then
          index = index Mod mCurrentSize
        End If
      Next
      If index = 0 Then index = index + 1
      calcInitIndex = index
    End Function
    
    Private Function stringToByteArray(Byval s)
      Dim i, byteArray()
      Redim byteArray(Len(s))
      For i = 1 To Len(s)
        byteArray(i) = Asc(Mid(s,i,1))
      Next
      stringToByteArray = byteArray
    End Function

    Private Function getValue(ByVal Key)
      Dim index
      index = findIndex(Key)
      If index > 0 Then
        getValue = mArray(index).Value
      Else
        Err.Raise 1012,, "[SunSoft]未指定默认值"
      End If
    End Function

    Private Sub addOrUpdate(ByVal Key, ByVal Value)
      Dim index
      Dim item
      '寻找是否现存此关键词
      index = findIndex(Key)
      '如果没有，则寻找一个现存空位
      If index <= 0 Then
        index = findFreeIndex(Key)
        mCount = mCount + 1
      End If
      '如果没找到
      If index < 0 Then
        '扩大空间
        Call expandArray
        '再挑一个位置
        index = findFreeIndex(Key)
      End If
      
      Set item = New ArrayElement
      item.IsTaken = True
      item.Key = Key
      item.Value = Value
      Set mArray(index) = Nothing
      Set mArray(index) = item
    End Sub
    
    '公有属性

    Public Property Get GapSize()
      GapSize = mGapSize
    End Property

    Public Property Let GapSize(ByVal newValue)
      If mCount > 0 Then
        Err.Raise 1000, , "[SunSoft]已经有数据，容量的增量不得修改"
      End If
      If newValue <= 0 Then
        Err.Raise 1001, , "[SunSoft]容量的增量不得为负数"
      End If
      mGapSize = newValue
    End Property
    
    Public Property Get Item(Byval Key)
      Item = getValue(Key)
    End Property
    
    Public Property Let Item(ByVal Key, ByVal Value)
      If VarType(Key) = 8 Then
        addOrUpdate Key, Value
      Else
        Err.Raise 1012,, "[SunSoft]键字段只能为字符串"
      End If
    End Property
    
    Public Property Get Count()
      Count = mCount
    End Property
    
    '公有方法

    Public Sub Add(ByVal Key, ByVal Value)
      If KeyExist(Key) Then
        Err.Raise 1011,, "[SunSoft]键重复"
      Else
        addOrUpdate Key, Value
      End If
    End Sub
    
    Public Function TryGet(ByVal Key,ByVal DefValue)
      On Error Resume Next
      Dim Value
      Value = getValue(Key)
      If Err.Number > 0 Then
        TryGet = DefValue
      Else
        TryGet = Value
      End If
      Err.Clear
    End Function
    
    Public Function KeyExist(ByVal Key)
      If findIndex(Key) < 0 Then
        KeyExist = False
      Else
        KeyExist = True
      End If
    End Function

  End Class
%>